﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using SPMS.Commons.Logging;
using SPMS.Utility;

namespace SPMS.Log
{
    /// <summary>
    /// 日志级别
    /// </summary>
    /// <remarks>定义了日志级别</remarks>
    /// <history>
    /// [zanezeng]               2009/9/22 15:46    创建
    /// </history>
    [TypeConverter( typeof( LevelTypeConverter ) )]
    public class Level : IComparable, IComparable<Level>
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="Level"/>的新实例
        /// </summary>
        /// <param name="value">日志级别的值</param>
        /// <param name="name">日志级别的名称</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为空或者为空字符串</exception>
        /// <history>
        /// [zanezeng]               2009/9/22 15:47    创建
        /// </history>
        public Level( string name, int value )
            : this( name, value, name )
        {
        }

        /// <summary>
        /// 初始化类型<see cref="Level"/>的新实例
        /// </summary>
        /// <param name="name">日志级别的名称</param>
        /// <param name="value">日志级别的值</param>
        /// <param name="displayName">日志级别的显示名称</param>
        /// <remarks></remarks>
        /// <exception cref="ArgumentNullException"><paramref name="name"/>为空或者为空字符串</exception>
        /// <history>
        /// [zanezeng]               2009/10/12 16:13    创建
        /// </history>
        public Level( string name, int value, string displayName )
        {
            //断言参数
            ArgumentAssert.AssertStringArgumentNotNullOrEmpty( name, "name" );

            //保存参数
            this.m_Name = name;
            this.m_Value = value;
            this.m_DisplayName = (string.IsNullOrEmpty( displayName )) ? name : displayName;
        }

        #endregion

        #region ---IComparable

        /// <summary>
        /// 比较当前实例与同一类型的另一对象
        /// </summary>
        /// <param name="obj">与当前实例进行比较的对象</param>
        /// <returns>
        /// 	<para>比较结果：</para>
        /// 	<list type="Table">
        /// 		<listheader>
        /// 			<term>值</term>
        /// 			<term>含义</term>
        /// 		</listheader>
        /// 		<item>
        /// 			<term>小于0</term>
        /// 			<term>当前实例小于<paramref name="obj"/></term>
        /// 		</item>
        /// 		<item>
        /// 			<term>等于0</term>
        /// 			<term>当前实例等于<paramref name="obj"/></term>
        /// 		</item>
        /// 		<item>
        /// 			<term>大于0</term>
        /// 			<term>当前实例大于<paramref name="obj"/></term>
        /// 		</item>
        /// 	</list>
        /// </returns>
        /// <exception cref="T:System.ArgumentException">
        /// 	<paramref name="obj"/>不具有与此实例相同的类型
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 9:40    创建
        /// </history>
        public int CompareTo( object obj )
        {
            //判断是否为NULL
            if (null == obj)
            {
                //如果为NULL，认为当期实例大于传入对象
                return 1;
            }

            //判断传入的对象是否为Level对象
            if (!(obj is Level))
            {
                //抛出异常
                throw new ArgumentException( Log.Properties.Resources.MSG_LEVEL_ARGMUSTBESTRING );
            }

            //进行比较
            return Compare( this, obj as Level );
        }

        #endregion

        #region ---IComparable<Level>

        /// <summary>
        /// 比较当前实例与同一类型的另一对象
        /// </summary>
        /// <param name="other">与当前实例进行比较的对象</param>
        /// <returns>
        /// 	<para>比较结果：</para>
        /// 	<list type="Table">
        /// 		<listheader>
        /// 			<term>值</term>
        /// 			<term>含义</term>
        /// 		</listheader>
        /// 		<item>
        /// 			<term>小于0</term>
        /// 			<term>当前实例小于<paramref name="other"/></term>
        /// 		</item>
        /// 		<item>
        /// 			<term>等于0</term>
        /// 			<term>当前实例等于<paramref name="other"/></term>
        /// 		</item>
        /// 		<item>
        /// 			<term>大于0</term>
        /// 			<term>当前实例大于<paramref name="other"/></term>
        /// 		</item>
        /// 	</list>
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 9:52    创建
        /// </history>
        public int CompareTo( Level other )
        {
            //判断是否为NULL
            if (null == other)
            {
                //如果为NULL，认为当期实例大于传入对象
                return 1;
            }

            //进行比较
            return Compare( this, other );
        }

        #endregion

        #region ---Public Method

        /// <summary>
        /// 比较两个<see cref="Level"/>对象的大小
        /// </summary>
        /// <param name="leftLevel">左侧的日志级别</param>
        /// <param name="rightLevel">右侧的日志级别</param>
        /// <returns>
        /// 	<para>比较结果：</para>
        /// 	<list type="Table">
        /// 		<listheader>
        /// 			<term>值</term>
        /// 			<term>含义</term>
        /// 		</listheader>
        /// 		<item>
        /// 			<term>小于0</term>
        /// 			<term><paramref name="leftLevel"/>小于<paramref name="rightLevel"/></term>
        /// 		</item>
        /// 		<item>
        /// 			<term>等于0</term>
        /// 			<term><paramref name="leftLevel"/>等于<paramref name="rightLevel"/></term>
        /// 		</item>
        /// 		<item>
        /// 			<term>大于0</term>
        /// 			<term><paramref name="leftLevel"/>大于<paramref name="rightLevel"/></term>
        /// 		</item>
        /// 	</list>
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/24 9:54    创建
        /// </history>
        public static int Compare( Level leftLevel, Level rightLevel )
        {
            //判断左侧的级别是否为NULL
            if (null == leftLevel)
            {
                //判断右侧的级别是否为NULL
                if (null == rightLevel)
                {
                    //认为相等
                    return 0;
                }

                //认为左侧的级别小于右侧的级别
                return -1;
            }

            //判断右侧的级别是否为NULL
            if (null == rightLevel)
            {
                //认为左侧的级别大于右侧的级别
                return 1;
            }

            //进行比较
            if (leftLevel.Value > rightLevel.Value)
            {
                //认为左侧的级别大于右侧的级别
                return 1;
            }
            else if (leftLevel.Value < rightLevel.Value)
            {
                //认为左侧的级别小于右侧的级别
                return -1;
            }

            //默认为相等
            return 0;
        }

        /// <summary>
        /// 确定指定的<see cref="Object"/>是否等于当前的<see cref="Level"/>
        /// </summary>
        /// <param name="obj">与当前的<see cref="Level"/>进行比较的<see cref="Object"/></param>
        /// <returns>
        /// 如果指定的<see cref="Object"/>等于当前的<see cref="Level"/>，则为<c>true</c>；否则为<c>false</c>。
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// <paramref name="obj"/>为Null
        /// </exception>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:52    创建
        /// </history>
        public override bool Equals( object obj )
        {
            //判断是否为Null
            if (null == obj)
            {
                //认为不等
                return false;
            }

            //转化为日志级别对象
            Level level = obj as Level;

            //如果不是日志级别对象，则认为不等
            if (null == level)
            {
                return false;
            }

            //比较日志级别的值
            return level.Value == this.m_Value;
        }

        /// <summary>
        /// 生成一个与对象的值相对应的数字以支持哈希表的使用
        /// </summary>
        /// <returns>当前<see cref="Level"/>对象的哈希代码</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:52    创建
        /// </history>
        public override int GetHashCode()
        {
            return this.m_Value;
        }

        /// <summary>
        /// 返回表示当前<see cref="Level"/>对象的<see cref="String"/>对象
        /// </summary>
        /// <returns>
        /// 表示当前<see cref="Level"/>对象的<see cref="String"/>对象
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:52    创建
        /// </history>
        public override string ToString()
        {
            return this.m_Name;
        }

        #endregion

        #region ---Operators

        /// <summary>
        /// 重载==操作符
        /// </summary>
        /// <param name="leftLevel">左侧的日志级别</param>
        /// <param name="rightLevel">右侧的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：左侧的日志级别等于右侧的日志级别<br/>
        /// 	<c>false</c>：左侧的日志级别不等于右侧的日志级别
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 17:42    创建
        /// </history>
        public static bool operator ==( Level leftLevel, Level rightLevel )
        {
            //判断是否为同一个对象
            if (object.ReferenceEquals( leftLevel, rightLevel ))
            {
                //如果是同一个对象，则认为相等
                return true;
            }

            //判断是否为NULL
            if ((object)leftLevel == null || (object)rightLevel == null)
            {
                //如果为任何一个为Null，则认为不相等
                return false;
            }

            //比较日志值是否相等
            return leftLevel.Value == rightLevel.Value;
        }

        /// <summary>
        /// 重载!=操作符
        /// </summary>
        /// <param name="leftLevel">左侧的日志级别</param>
        /// <param name="rightLevel">右侧的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：左侧的日志级别不等于右侧的日志级别<br/>
        /// 	<c>false</c>：左侧的日志级别等于右侧的日志级别
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/16 17:42    创建
        /// </history>
        public static bool operator !=( Level leftLevel, Level rightLevel )
        {
            return !(leftLevel == rightLevel);
        }

        /// <summary>
        /// 重载 &gt;操作服务
        /// </summary>
        /// <param name="leftLevel">左侧的日志级别</param>
        /// <param name="rightLevel">右侧的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：左侧的日志级别大于右侧的日志级别<br/>
        /// 	<c>false</c>：左侧的日志级别小于右侧的日志级别
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:50    创建
        /// </history>
        public static bool operator >( Level leftLevel, Level rightLevel )
        {
            //判断是否为Null
            if (null == (object)leftLevel)
            {
                leftLevel = Level.All;
            }

            //判断是否为Null
            if (null == (object)rightLevel)
            {
                rightLevel = Level.All;
            }

            //返回比较
            return leftLevel.Value > rightLevel.Value;
        }

        /// <summary>
        /// 重载 &lt;操作服务
        /// </summary>
        /// <param name="leftLevel">左侧的日志级别</param>
        /// <param name="rightLevel">右侧的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：左侧的日志级别大于右侧的日志级别<br/>
        /// 	<c>false</c>：左侧的日志级别小于右侧的日志级别
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:50    创建
        /// </history>
        public static bool operator <( Level leftLevel, Level rightLevel )
        {
            //判断是否为Null
            if (null == (object)leftLevel)
            {
                leftLevel = Level.All;
            }

            //判断是否为Null
            if (null == (object)rightLevel)
            {
                rightLevel = Level.All;
            }

            //返回比较
            return leftLevel.Value < rightLevel.Value;
        }

        /// <summary>
        /// 重载 &lt;=操作服务
        /// </summary>
        /// <param name="leftLevel">左侧的日志级别</param>
        /// <param name="rightLevel">右侧的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：左侧的日志级别大于右侧的日志级别<br/>
        /// 	<c>false</c>：左侧的日志级别小于右侧的日志级别
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:50    创建
        /// </history>
        public static bool operator <=( Level leftLevel, Level rightLevel )
        {
            //判断是否为Null
            if (null == (object)leftLevel)
            {
                leftLevel = Level.All;
            }

            //判断是否为Null
            if (null == (object)rightLevel)
            {
                rightLevel = Level.All;
            }

            //返回比较
            return leftLevel.Value <= rightLevel.Value;
        }

        /// <summary>
        /// 重载 &gt;= 操作服务
        /// </summary>
        /// <param name="leftLevel">左侧的日志级别</param>
        /// <param name="rightLevel">右侧的日志级别</param>
        /// <returns>
        /// 	<c>true</c>：左侧的日志级别大于右侧的日志级别<br/>
        /// 	<c>false</c>：左侧的日志级别小于右侧的日志级别
        /// </returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:50    创建
        /// </history>
        public static bool operator >=( Level leftLevel, Level rightLevel )
        {
            //判断是否为Null
            if (null == (object)leftLevel)
            {
                leftLevel = Level.All;
            }

            //判断是否为Null
            if (null == (object)rightLevel)
            {
                rightLevel = Level.All;
            }

            //返回比较
            return leftLevel.Value >= rightLevel.Value;
        }

        #endregion

        #region ---Property

        /// <summary>
        /// 获得日志级别的值
        /// </summary>
        /// <value>日志级别的值</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:53    创建
        /// </history>
        public int Value
        {
            get
            {
                return this.m_Value;
            }
        }

        /// <summary>
        /// 获得日志级别的名称
        /// </summary>
        /// <value>日志级别的名称</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/22 15:53    创建
        /// </history>
        public string Name
        {
            get
            {
                return this.m_Name;
            }
        }

        /// <summary>
        /// 获得日志级别的显示名称
        /// </summary>
        /// <value>日志级别的显示名称</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/10/12 16:16    创建
        /// </history>
        public string DisplayName
        {
            get
            {
                return this.m_DisplayName;
            }
        }

        #endregion

        #region ---Const

        /// <summary>
        /// 全部输出日志级别
        /// </summary>
        public static readonly Level All = new Level( "All", LEVEL_ALL, Properties.Resources.MSG_LEVEL_ALL );

        /// <summary>
        /// 详细信息日志级别
        /// </summary>
        public static readonly Level Verbose = new Level( "Verbose", 1000, Properties.Resources.MSG_LEVEL_VERBOSE );

        /// <summary>
        /// 跟踪信息日志级别
        /// </summary>
        public static readonly Level Trace = new Level( "Trace", 4000, Properties.Resources.MSG_LEVEL_TRACE );

        /// <summary>
        /// 正常信息日志级别
        /// </summary>
        public static readonly Level Fine = new Level( "Fine", 5000, Properties.Resources.MSG_LEVEL_FINE );

        /// <summary>
        /// 调试信息日志级别
        /// </summary>
        public static readonly Level Debug = new Level( "Debug", 8000, Properties.Resources.MSG_LEVEL_DEBUG );

        /// <summary>
        /// 提示信息日志级别
        /// </summary>
        public static readonly Level Info = new Level( "Info", 20000, Properties.Resources.MSG_LEVEL_INFO );

        /// <summary>
        /// 注意信息日志级别
        /// </summary>
        public static readonly Level Notice = new Level( "Notice", 40000, Properties.Resources.MSG_LEVEL_NOTICE );

        /// <summary>
        /// 警告信息日志级别
        /// </summary>
        public static readonly Level Warn = new Level( "Warn", 60000, Properties.Resources.MSG_LEVEL_WARN );

        /// <summary>
        /// 错误信息日志级别
        /// </summary>
        public static readonly Level Error = new Level( "Error", 200000, Properties.Resources.MSG_LEVEL_ERROR );

        /// <summary>
        /// 严重错误信息日志级别
        /// </summary>
        public static readonly Level Severe = new Level( "Severe", 300000, Properties.Resources.MSG_LEVEL_SEVERE );

        /// <summary>
        /// 危急信息级别
        /// </summary>
        public static readonly Level Critical = new Level( "Critical", 400000, Properties.Resources.MSG_LEVEL_CRITICAL );

        /// <summary>
        /// 警报信息级别
        /// </summary>
        public static readonly Level Alert = new Level( "Alert", 500000, Properties.Resources.MSG_LEVEL_ALERT );

        /// <summary>
        /// 重大错误信息级别
        /// </summary>
        public static readonly Level Fatal = new Level( "Fatal", 600000, Properties.Resources.MSG_LEVEL_FATAL );

        /// <summary>
        /// 紧急信息级别
        /// </summary>
        public static readonly Level Emergency = new Level( "Emergency", 700000, Properties.Resources.MSG_LEVEL_EMERGENCY );

        /// <summary>
        /// 关闭日志输出级别
        /// </summary>
        public static readonly Level Off = new Level( "Off", LEVEL_OFF, Properties.Resources.MSG_LEVEL_OFF );

        #endregion

        #region ---Field

        /// <summary>
        /// 日志级别的值
        /// </summary>
        private int m_Value;

        /// <summary>
        /// 日志级别的名称
        /// </summary>
        private string m_Name;

        /// <summary>
        /// 日志的显示名称
        /// </summary>
        private string m_DisplayName;

        /// <summary>
        /// 全部输出日志的级别
        /// </summary>
        private const int LEVEL_ALL = int.MinValue;

        /// <summary>
        /// 不输出日志级别
        /// </summary>
        private const int LEVEL_OFF = int.MaxValue;

        #endregion
    }
}
